package com.ssy.lingxi.purchase.serviceimpl.tender;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.purchase.api.dto.request.tender.ExpertExtractBatchQueryRequest;
import com.ssy.lingxi.purchase.api.dto.request.tender.ExpertQueryRequest;
import com.ssy.lingxi.purchase.api.dto.request.tender.StatusRequest;
import com.ssy.lingxi.purchase.entity.tender.Expert;
import com.ssy.lingxi.purchase.entity.tender.ExpertExtractRecord;
import com.ssy.lingxi.purchase.repository.tender.ExpertExtractRecordRepository;
import com.ssy.lingxi.purchase.repository.tender.ExpertRepository;
import com.ssy.lingxi.purchase.service.tender.IExpertService;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * 评标专家库实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class ExpertServiceImpl implements IExpertService {

    @Resource
    private ExpertRepository expertRepository;

    @Resource
    private ExpertExtractRecordRepository expertExtractRecordRepository;

    /**
     * 查询评标专家库列表
     * @param pageVO 分页实体
     * @param expertQueryRequest 评标专家库
     * @return
     */
    @Override
    public Page<Expert> getExpertList(UserLoginCacheDTO sysUser, PageVO pageVO, ExpertQueryRequest expertQueryRequest){
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        return expertRepository.findAll(getSpecification(sysUser, expertQueryRequest), page);
    }

    /**
     * 查询评标专家库列表--按条件抽取
     * @param sysUser
     * @param expertBatchQueryRequestList
     * @return
     */
    @Override
    public List<Expert> getBatchExpertList(UserLoginCacheDTO sysUser, List<ExpertExtractBatchQueryRequest> expertBatchQueryRequestList) {
        List<Expert> expertList = new ArrayList<>();
        expertBatchQueryRequestList.forEach(expertBatchQueryRequest -> {
            Integer count = expertBatchQueryRequest.getCount();
            if(count != null && count > 0){
                Pageable page = PageRequest.of(0, count);
                Page<Expert> expertPageList = expertRepository.findAll(getSpecificationBatch(sysUser, expertBatchQueryRequest), page);
                List<Expert> content = expertPageList.getContent();
                if(content.size() > 0){
                    expertList.addAll(content);
                }
            }
        });
        return expertList;
    }

    /**
     * 查询评标专家库
     * @return id
     */
    @Override
    public Expert getExpert(UserLoginCacheDTO sysUser, Long id){
        return expertRepository.findById(id).orElse(null);
    }

    /**
     * 添加/修改评标专家库
     * @param expert
     * @return
     */
    @Override
    public String saveOrUpdateExpert(UserLoginCacheDTO sysUser, Expert expert){
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();
        Long userId = sysUser.getUserId();
        //判断名称是否重复
        Long id = expert.getId();
        if(id != null && id > 0){
            Expert currentExpert = expertRepository.findById(id).orElse(null);
            if(currentExpert == null){
                throw new BusinessException(ResponseCode.PURCHASE_TENDER_EXPERT_NOT_EXIST);
            }
            //数据库持久化对象
            CopyOptions copyOptions = new CopyOptions();
            copyOptions.setIgnoreProperties("id");
            copyOptions.setIgnoreNullValue(true);
            BeanUtil.copyProperties(expert, currentExpert, copyOptions);
            expertRepository.saveAndFlush(currentExpert);
        }else{
            expert.setMemberId(memberId);
            expert.setMemberName(sysUser.getCompany());
            expert.setMemberRoleId(memberRoleId);
            expert.setMemberRoleName(sysUser.getMemberRoleName());
            expert.setUserId(userId);
            expert.setUserName(sysUser.getUserName());
            expert.setCreateTime(System.currentTimeMillis());
            //数据库持久化对象
            expertRepository.saveAndFlush(expert);
        }

        return ResponseCode.SUCCESS.getMessage();
    }

    /**
     * 修改评标专家库状态
     * @param sysUser
     * @param statusRequest
     * @return
     */
    @Override
    public Boolean updateExpertStatus(UserLoginCacheDTO sysUser, StatusRequest statusRequest) {
        Long id = statusRequest.getId();
        Boolean status = statusRequest.getStatus();
        if(id != null){
            Expert expert = expertRepository.findById(id).orElse(null);
            if(expert != null){
                expert.setStatus(status);
                if(!status){
                    expert.setUpdateTime(System.currentTimeMillis());
                }
                expertRepository.saveAndFlush(expert);
                return true;
            }
        }
        throw new BusinessException(ResponseCode.PURCHASE_TENDER_EXPERT_NOT_EXIST);
    }

    /**
     * 批量删除评标专家库
     * @param idList
     * @return
     */
    @Override
    public String deleteBatchExpert(UserLoginCacheDTO sysUser, List<Long> idList) {
        //判断评标专家库是否存在
        List<Expert> expertList = expertRepository.findByMemberIdAndMemberRoleIdAndIdIn(sysUser.getMemberId(), sysUser.getMemberRoleId(), idList);
        if(expertList.isEmpty() || expertList.size() != idList.size()){
            throw new BusinessException(ResponseCode.PURCHASE_TENDER_EXPERT_NOT_EXIST);
        }
        //判断专家抽取记录中是否存在
        List<ExpertExtractRecord> expertExtractRecordList = expertExtractRecordRepository.findByExpertIdIn(idList);
        if(expertExtractRecordList != null && expertExtractRecordList.size() > 0){
            throw new BusinessException(ResponseCode.PURCHASE_EXPERT_NOT_DELETE);
        }
        expertRepository.deleteAll(expertList);
        return ResponseCode.SUCCESS.getMessage();
    }

    /**
     * 构建查询条件
     * @param sysUser
     * @return
     */
    private Specification<Expert> getSpecification(UserLoginCacheDTO sysUser, ExpertQueryRequest expertQueryRequest){
        return new Specification<Expert>() {
            @Override
            public Predicate toPredicate(Root<Expert> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate finalConditions = criteriaBuilder.conjunction();

                String name = expertQueryRequest.getName();
                String phone = expertQueryRequest.getPhone();
                String qualification = expertQueryRequest.getQualification();
                Integer speciality = expertQueryRequest.getSpeciality();
                Boolean status = expertQueryRequest.getStatus();
                String title = expertQueryRequest.getTitle();
                Integer type = expertQueryRequest.getType();
                String userJobTitle = expertQueryRequest.getUserJobTitle();
                String userOrgName = expertQueryRequest.getUserOrgName();

                if(!StringUtils.isEmpty(name)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("name").as(String.class), "%" + name + "%"));
                }
                if(!StringUtils.isEmpty(phone)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("phone").as(String.class), "%" + phone + "%"));
                }
                if(!StringUtils.isEmpty(qualification)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("qualification").as(String.class), "%" + qualification + "%"));
                }
                if(!StringUtils.isEmpty(title)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("title").as(String.class), "%" + title + "%"));
                }
                if(!StringUtils.isEmpty(userJobTitle)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("userJobTitle").as(String.class), "%" + userJobTitle + "%"));
                }
                if(!StringUtils.isEmpty(userOrgName)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("userOrgName").as(String.class), "%" + userOrgName + "%"));
                }

                if(speciality != null && speciality > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("speciality"), speciality));
                }
                if(type != null && type > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("type"), type));
                }

                if(status != null){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("status"), status));
                }
                if(sysUser.getMemberId() != null && sysUser.getMemberId() > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberId").as(Long.class), sysUser.getMemberId()));
                }
                if(sysUser.getMemberRoleId() != null && sysUser.getMemberRoleId() > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberRoleId").as(Long.class), sysUser.getMemberRoleId()));
                }
                query.orderBy(criteriaBuilder.desc(root.get("id")));
                return finalConditions;
            }
        };
    }

    /**
     * 构建查询条件
     * @param sysUser
     * @return
     */
    private Specification<Expert> getSpecificationBatch(UserLoginCacheDTO sysUser, ExpertExtractBatchQueryRequest expertBatchQueryRequest){
        return new Specification<Expert>() {
            @Override
            public Predicate toPredicate(Root<Expert> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate finalConditions = criteriaBuilder.conjunction();

                String provinceCode = expertBatchQueryRequest.getProvinceCode();
                String cityCode = expertBatchQueryRequest.getCityCode();
                String areaCode = expertBatchQueryRequest.getAreaCode();
                String excludeProvinceCode = expertBatchQueryRequest.getExcludeProvinceCode();
                String excludeCityCode = expertBatchQueryRequest.getExcludeCityCode();
                String excludeAreaCode = expertBatchQueryRequest.getExcludeAreaCode();
                String qualification = expertBatchQueryRequest.getQualification();
                Integer speciality = expertBatchQueryRequest.getSpeciality();
                String title = expertBatchQueryRequest.getTitle();
                Integer type = expertBatchQueryRequest.getType();
                String trade = expertBatchQueryRequest.getTrade();
                String unit = expertBatchQueryRequest.getUnit();
                Integer years = expertBatchQueryRequest.getYears();


                if(!StringUtils.isEmpty(provinceCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("provinceCode").as(String.class), provinceCode));
                }
                if(!StringUtils.isEmpty(cityCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("cityCode").as(String.class), cityCode));
                }
                if(!StringUtils.isEmpty(areaCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("areaCode").as(String.class), areaCode));
                }

                if(!StringUtils.isEmpty(excludeProvinceCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.notEqual(root.get("provinceCode").as(String.class), excludeProvinceCode));
                }
                if(!StringUtils.isEmpty(excludeCityCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.notEqual(root.get("cityCode").as(String.class), excludeCityCode));
                }
                if(!StringUtils.isEmpty(excludeAreaCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.notEqual(root.get("areaCode").as(String.class), excludeAreaCode));
                }

                if(!StringUtils.isEmpty(trade)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("trade").as(String.class), "%" + trade + "%"));
                }
                if(!StringUtils.isEmpty(unit)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("unit").as(String.class), "%" + unit + "%"));
                }
                if(!StringUtils.isEmpty(qualification)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("qualification").as(String.class), "%" + qualification + "%"));
                }
                if(!StringUtils.isEmpty(title)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("title").as(String.class), "%" + title + "%"));
                }

                if(speciality != null && speciality > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("speciality"), speciality));
                }
                if(type != null && type > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("type"), type));
                }
                if(years != null && years > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("years"), years));
                }
                if(sysUser.getMemberId() != null && sysUser.getMemberId() > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberId").as(Long.class), sysUser.getMemberId()));
                }
                if(sysUser.getMemberRoleId() != null && sysUser.getMemberRoleId() > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberRoleId").as(Long.class), sysUser.getMemberRoleId()));
                }
                query.orderBy(criteriaBuilder.desc(root.get("id")));
                return finalConditions;
            }
        };
    }
}

